import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;

// StudentMazeGenerator.java
//
// ICS 23 Summer 2004
// Project #1: Dark at the End of the Tunnel

// The StudentMazeGenerator class is where you should implement your maze
// generation algorithm.  Presently, it returns a newly-created maze, in which
// every wall exists.

public class StudentMazeGenerator implements MazeGenerator {
	private enum Direction {
		EAST, NORTH, SOUTH, WEST
	}

	private ArrayList<Point> m_unvisitedNeighbors;

	private ArrayList<Direction> getUnvisitedNeighbors(int a_x, int a_y,
			boolean[][] a_visited, Maze a_maze) {

		ArrayList<Direction> neighbors = new ArrayList<Direction>();

		System.out.println("width | height : " + a_maze.getWidth() + " "
				+ a_maze.getHeight());
		System.out.println("curX | curY : " + a_x + " " + a_y);
		if (a_x + 1 < a_maze.getWidth() && !a_visited[a_y][a_x + 1]) {
			Point temp = new Point(a_x + 1, a_y);
			if (!m_unvisitedNeighbors.contains(temp))
				m_unvisitedNeighbors.add(temp);
			neighbors.add(Direction.EAST);
		}
		if (a_y - 1 > 0 && !a_visited[a_y - 1][a_x]) {
			Point temp = new Point(a_x, a_y - 1);
			if (!m_unvisitedNeighbors.contains(temp))
				m_unvisitedNeighbors.add(temp);
			neighbors.add(Direction.NORTH);
		}
		if (a_y + 1 < a_maze.getHeight() && !a_visited[a_y + 1][a_x]) {
			Point temp = new Point(a_x, a_y + 1);
			if (!m_unvisitedNeighbors.contains(temp))
				m_unvisitedNeighbors.add(temp);
			neighbors.add(Direction.SOUTH);
		}
		if (a_x - 1 > 0 && !a_visited[a_y][a_x - 1]) {
			Point temp = new Point(a_x - 1, a_y);
			if (!m_unvisitedNeighbors.contains(temp))
				m_unvisitedNeighbors.add(temp);
			neighbors.add(Direction.WEST);
		}
		return neighbors;
	}

	public Maze generateMaze(int width, int height,
			MazeGeneratorListener listener) {

		Maze maze = MazeFactory.createMaze(width, height);
		Random rand = new Random(System.currentTimeMillis());

		// initialize m_visited
		boolean[][] m_visited = new boolean[height][width];
		m_unvisitedNeighbors = new ArrayList<Point>();
		ArrayList<Direction> m_neighbors = null;
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				m_visited[y][x] = false;
			}
		}
		int curX = maze.getStartXPosition();
		int curY = maze.getStartYPosition();

		do {
			System.out.println("size of m_unvisitedNeighbors : " + m_unvisitedNeighbors.size());
			m_visited[curY][curX] = true;
			m_neighbors = getUnvisitedNeighbors(curX, curY, m_visited, maze);

			if (m_neighbors.size() > 0) {
				int index = rand.nextInt(m_neighbors.size());
				System.out.println("SIZE OF NEIGHBORS:" + m_neighbors.size()
						+ "\n");
				System.out.println("randomIndex: " + index);
				Direction dir = m_neighbors.get(index);
				switch (dir) {
					case EAST:{
						System.out.println("EAST WALL REMOVED of [");
						System.out.println(curX + "," + curY + "]");
						maze.removeWallEastOf(curX, curY);
//						Point temp = new Point(curX+1,curY);
//						if(m_unvisitedNeighbors.contains(temp))
//							m_unvisitedNeighbors.remove(temp);
						curX++;
						break;}
					case NORTH:{
						System.out.println("NORTH WALL REMOVED of [");
						System.out.println(curX + "," + curY + "]");
						maze.removeWallNorthOf(curX, curY);
//						Point temp = new Point(curX,curY-1);
//						if(m_unvisitedNeighbors.contains(temp))
//							m_unvisitedNeighbors.remove(temp);
						curY--;
						break;}
					case SOUTH:{
						System.out.println("SOUTH WALL REMOVED of [");
						System.out.println(curX + "," + curY + "]");
//						Point temp = new Point(curX,curY+1);
//						if(m_unvisitedNeighbors.contains(temp))
//							m_unvisitedNeighbors.remove(temp);
						maze.removeWallSouthOf(curX, curY);
						curY++;
						break;}
					case WEST:{
						System.out.println("WEST WALL REMOVED of [");
						System.out.println(curX + "," + curY + "]");
						
//						Point temp = new Point(curX-1,curY);
//						if(m_unvisitedNeighbors.contains(temp))
//							m_unvisitedNeighbors.remove(temp);
						maze.removeWallWestOf(curX, curY);
						curX--;
						break;}
				}
				listener.mazeModified(maze);
			}
			else{
				Point xy = m_unvisitedNeighbors.remove(0);
				curX = xy.x;
				curY = xy.y;
				System.out.println("m_neighbors.size() == 0");
			}
		} while (m_unvisitedNeighbors.size() > 0);
		return maze;
		// // mark current cell as visited
		// m_visited[curY][curX] = true;
		// m_neighbors = getNeighbors(curX, curY, m_visited, maze);
		// // if the current cell has any adjacent cells that have not yet been
		// visited
		// if(m_neighbors.size() > 0){
		// //Choose one of the unvisited adjacent cells at random. Randomness
		// //is important here, or your algorithm will always generate the same
		// maze.
		// Direction dirToRemove = m_neighbors.get(rand.nextInt() %
		// m_neighbors.size());
		// // Remove the wall between the current cell and the cell you just
		// chose.
		// // then Recursively call the algorithm, with the chosen cell becoming
		// the current cell.
		// switch(dirToRemove){
		// case EAST:
		// maze.removeWallEastOf(curX, curY);
		// curX++;
		// break;
		// case NORTH:
		// maze.removeWallNorthOf(curX, curY);
		// curY--;
		// break;
		// case SOUTH:
		// maze.removeWallSouthOf(curX, curY);
		// curY++;
		// break;
		// case WEST:
		// maze.removeWallWestOf(curX, curY);
		// curX--;
		// break;
		//					
		// }
		// count--;
		// listener.mazeModified(maze);
		// }
		//			
		//			
		//			
		// }
		// // TODO END-LOOP
		// return maze;
		//		
	}
}